package com.hourse.platform.controller;

import com.hourse.platform.common.CommonState;
import com.hourse.app.utils.ImageUtil;
import com.hourse.app.utils.VerificationCodeUtil;
import com.hourse.platform.common.ErrorMsg;
import com.hourse.platform.common.LoginKey;
import com.hourse.platform.entity.UserEntity;
import com.hourse.platform.entity.UserRoleEntity;
import com.hourse.platform.exception.ValidateException;
import com.hourse.platform.service.AuthService;
import com.hourse.platform.service.RoleService;
import com.hourse.platform.service.UserService;
import com.hourse.platform.utils.AppTools;
import com.hourse.platform.utils.BeanTools;
import com.hourse.platform.utils.CurrentThread;
import com.hourse.platform.utils.StringTools;
import com.hourse.platform.vo.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Api(tags = "系统-用户服务")
@RestController
@RequestMapping("platform/user")
@Slf4j
public class UserController {

    @Autowired
    private RedisTemplate redisTemplate;

    // 登录有效时间
    private static Integer LoginKeyTime;

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private AuthService authService;

    @Value("${loginKeyTime}")
    public void setLoginKeyTime(Integer loginKeyTime) {
        LoginKeyTime = loginKeyTime;
    }

    /**
     * @功能描述: 【用户登陆】
     */
    @SneakyThrows
    @PostMapping(value = "/login")
    public PageData login(@RequestBody UserLoginVO userLoginVO) {


        BeanTools.Validate(userLoginVO);

        String pass = AppTools.EncryptionPassword(userLoginVO.getAccount(), userLoginVO.getPassword());
        log.info("【用户登录】  ");
        log.info("【账号】:{}", userLoginVO.getAccount());
        log.info("【密码明文】:{}", userLoginVO.getPassword());
        log.info("【密码密文】:{}", pass);
        log.info(">>>>>>>>>>>>>>>>>>>>>");
        UserEntity userEntity = userService.getUser(userLoginVO.getAccount(), pass);

        // 用户不存在
        if (userEntity == null) {
            ErrorMsg.ACCOUNT_PASSWOR_ERR.Ex();
        }

        //图形验证码是否正确
        Object o = redisTemplate.opsForValue().get(CommonState.GVC.getValue() + userLoginVO.getAccount());
        if (!StringUtils.isEmpty(o) && !userLoginVO.getGraphVerifyCode().toUpperCase().equals(((String) o).toUpperCase())) {
            redisTemplate.delete(CommonState.GVC.getValue() + userLoginVO.getAccount());
            ErrorMsg.ERIFY_VODE_ERR.Ex();
        }
        redisTemplate.delete(CommonState.GVC.getValue() + userLoginVO.getAccount());

        UserSession userSession = new UserSession();
        String token = UUID.randomUUID().toString();

        userSession.setToken(token);
        userSession.setUserId(String.valueOf(userEntity.getId()));
        userSession.setAccount(userEntity.getAccount());
        CurrentThread.setUserId(userEntity.getId());
        userSession.setCurtRoleGroupId(userLoginVO.getRoleGroupId());
        String logkey = new LoginKey("user", userSession.getToken()).getKey();

        String key = (String) redisTemplate.opsForValue().get(userLoginVO.getAccount());

        if (StringTools.isNotNull(key)) {
            log.info("【账号重复登录】将原登录账号信息登出...");
            log.info("【账号】:{}", userLoginVO.getAccount());
            log.info("【当前令牌】:{}", logkey);
            log.info("【过期令牌】:{}", key);
            redisTemplate.delete(key);
        }

        // 角色组
        List<RoleVO> roleList = userService.getRoleList(AppTools.GetCurrentUserId());

        List<RoleVO> userRoleList = new ArrayList<>();

        for (RoleVO role : roleList) {
            if ("1".equals(role.getAuth())) {
                // 获取角色
                List<RoleGroupItemVO> itemVOList = roleService.roleGroupItemList(role.getId());

                for (RoleGroupItemVO roleItem : itemVOList) {
                    RoleVO roleVO = new RoleVO();
                    roleVO.setId(roleItem.getRoleId());
                    roleVO.setName(roleItem.getRoleName());
                    roleVO.setCode(roleItem.getRoleCode());
                    userRoleList.add(roleVO);
                    userSession.getRoles().add(roleVO.getCode());
                }
                // 添加角色组
                userRoleList.add(role);
                userSession.getRoles().add(role.getCode());
            }
        }

        userSession.getRoles().add("_$SYSTEM_USER");
        userSession.getRoles().add("_$SYSTEM_DEFAULT");

        userSession.setAdmin(false);
        for (String role : userSession.getRoles()) {
            if ("ADMIN".equals(role)) {
                userSession.setAdmin(true);
                CurrentThread.setAdminStatus(true);
                log.info("【管理员用户】:{}", userSession.getAccount());
                break;
            }
        }

        List<String> allowPaths = userService.getAllowPaths(userRoleList);
        userSession.setAllowPaths(allowPaths);

        redisTemplate.opsForValue().set(userLoginVO.getAccount(),
                logkey, LoginKeyTime, TimeUnit.SECONDS);

        redisTemplate.opsForValue().set(logkey,
                userSession, LoginKeyTime, TimeUnit.SECONDS);

        return new LoginTokenVO(userSession.getToken(),
                authService.getUserPageAuthInfo(),
                userService.getUserMenuList(),
                userRoleList, userEntity.getName(), userEntity.getAccount())
                .SUCCESS();
    }

    @SneakyThrows
    @PostMapping(value = "/logout")
    public PageData logout() {

        String logkey = new LoginKey("user", AppTools.GetCurrentToken()).getKey();
        UserSession userSession = (UserSession) redisTemplate.opsForValue().get(logkey);
        if (userSession != null) {
            log.info("【退出账号】: {}", userSession.getAccount());
            log.info("【退出令牌】: {}", logkey);
            redisTemplate.delete(userSession.getAccount());
            redisTemplate.delete(logkey);
        }

        return new PageData().SUCCESS();
    }

    /**
     * @功能描述: 【创建用户】
     * @作 者 : Rain
     * @创建时间 : 2020/11/30 13:17
     */
    @SneakyThrows
    @PostMapping(value = "/createUser")
    public PageData createUser(@RequestBody CreateUserVO createUserVO) {

        userService.createUser(createUserVO);

        return PageData.New().SUCCESS();
    }

    /**
     * @return : com.hourse.platform.vo.Message
     * @功能描述: 【获取用户列表】
     */
    @SneakyThrows
    @GetMapping(value = "userList")
    public ResultMsg<List<UserListVO>> userList() {

        return new ResultMsg(userService.getUserList());
    }

    /**
     * @return : com.hourse.platform.vo.Message
     * @功能描述: 【获取用户角色列表】
     */
    @SneakyThrows
    @GetMapping(value = "roleList/{userId}")
    public ResultMsg<List<UserListVO>> roleList(@PathVariable String userId) {

        return new ResultMsg(userService.getRoleList(userId));
    }

    /**
     * @功能描述: 【用户添加角色】
     */
    @SneakyThrows
    @PostMapping(value = "addUserRole")
    public PageData addUserRole(@RequestBody UserRoleVO userRoleVO) {

        UserRoleEntity roleEntity = (UserRoleEntity) userRoleVO.bindEnity(UserRoleEntity.class);
        roleEntity.setId(null);

        userService.save(roleEntity);
        return userRoleVO.SUCCESS();
    }

    /**
     * @功能描述: 【用户删除角色】
     */
    @SneakyThrows
    @PostMapping(value = "deleteUserRole")
    public PageData deleteUserRole(@RequestBody UserRoleVO userRoleVO) {

        userService.deleteUserRole(userRoleVO.getUserId(), userRoleVO.getRoleId());

        return userRoleVO.SUCCESS();
    }

    /**
     * @功能描述: 【获取用户菜单】
     * @作 者 : Rain
     * @创建时间 : 2020/11/29 16:48
     */
    @SneakyThrows
    @GetMapping(value = "menuList")
    public PageData menuList() {

        return new ResultMsg(userService.getUserMenuList());
    }

    /**
     * 获取图形验证码
     */
    @ApiOperation(value = "获取图形验证码")
    @GetMapping("/graphVerifyCode/{phone}")
    public PageData verifyCode(@PathVariable(value = "phone") String phone) {
        VerificationCodeUtil code = new VerificationCodeUtil();
        BufferedImage image = code.getImage();
        String text = code.getText();

        redisTemplate.opsForValue().set(CommonState.GVC.getValue() + phone, text, 60, TimeUnit.SECONDS);

        byte[] jpgs = ImageUtil.imageToBytes(image, "jpg");
        return PageData.New().SUCCESS(jpgs);
    }


    @ApiOperation(value = "修改用户密码")
    @PostMapping("/updateUserPassword")
    public PageData updateUserPassword(@RequestBody UpdateUserPasswordVO vo) {

        try {

            log.info("修改用户密码 请求信息:{}", vo);

            BeanTools.Validate(vo);

            UserEntity userEntity = userService.getUserAccount(vo.getPhone());

            if (null == userEntity) {
                return PageData.New().SUCCESS(ErrorMsg.DB_ERR.code(), "该数据不存在...");
            }
            String oldPassword = AppTools.EncryptionPassword(vo.getPhone(), vo.getOldPassword());

            if (!oldPassword.equals(userEntity.getPassword())) {
                return PageData.New().ERROR(ErrorMsg.SYSTEM_ERR.code(), "旧密码输入错误..");
            }

            String newPassword = AppTools.EncryptionPassword(vo.getPhone(), vo.getNewPassword());
            userEntity.setPassword(newPassword);

            userService.saveOrUpdate(userEntity);

            return PageData.New().SUCCESS();
        } catch (ValidateException e) {
            e.printStackTrace();
            return PageData.New().ERROR(ErrorMsg.BEAN_CHECK_ERR.code(), e.getMsg());
        } catch (Exception e) {
            e.printStackTrace();
            return PageData.New().ERROR(ErrorMsg.SYSTEM_ERR);
        }
    }

    @ApiOperation(value = "管理员重置用户密码")
    @GetMapping("/resetUserPassword/{phone}")
    public PageData resetUserPassword(@PathVariable("phone") String phone) {

        try {

            log.info("重置密码 请求信息:{}", phone);

            if (StringUtils.isEmpty(phone)) {
                return PageData.New().SUCCESS(ErrorMsg.BEAN_CHECK_ERR.code(), "手机号不能为空...");
            }

            UserEntity userEntity = userService.getUserAccount(phone);

            if (null == userEntity) {
                return PageData.New().SUCCESS(ErrorMsg.DB_ERR.code(), "该数据不存在...");
            }

            String password = AppTools.EncryptionPassword(phone, phone);
            userEntity.setPassword(password);

            userService.saveOrUpdate(userEntity);

            return PageData.New().SUCCESS();
        } catch (Exception e) {
            e.printStackTrace();
            return PageData.New().ERROR(ErrorMsg.SYSTEM_ERR);
        }
    }

}
